home *** CD-ROM | disk | FTP | other *** search
/ Aminet 30 / Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso / Aminet / util / cli / WBLaunch.lha / Source / wblaunch.c < prev   
C/C++ Source or Header  |  1999-02-14  |  11KB  |  380 lines

  1. /*
  2.  * wblaunch.c - WBLaunch main routines
  3.  * part of WBLaunch - emulates WB startup of programs from the Shell
  4.  * Copyright (C) 1998, 1999 Stephen Williams <sw@fysh.org>
  5.  * wbstart.library is copyright (C) Stefan Becker
  6.  *
  7.  * This program is free software; you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License as published by
  9.  * the Free Software Foundation; either version 2 of the License, or
  10.  * (at your option) any later version.
  11.  *
  12.  * This program is distributed in the hope that it will be useful,
  13.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  * GNU General Public License for more details.
  16.  *
  17.  * You should have received a copy of the GNU General Public License
  18.  * along with this program; if not, write to the Free Software
  19.  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  *
  21.  */
  22.  
  23.  
  24. #include <exec/memory.h>
  25. #include <dos/dos.h>
  26. #include <libraries/wbstart.h>
  27. #include <workbench/startup.h>
  28.  
  29. #include <clib/dos_protos.h>
  30. #include <clib/exec_protos.h>
  31. #include <clib/wbstart_protos.h>
  32.  
  33. #ifdef VBCC
  34. #include <inline/dos_protos.h>
  35. #include <inline/exec_protos.h>
  36. #endif
  37.  
  38. #include <string.h>
  39.  
  40.  
  41. /* Library bases */
  42. extern struct DosLibrary *    DOSBase;
  43. extern struct Library *        SysBase;
  44. struct Library *        WBStartBase;
  45.  
  46.  
  47. /* Constants for my readargs array */
  48. #define    ARG_PROGRAM    0
  49. #define    ARG_ARGUMENTS    1
  50. #define    ARG_PRI        2
  51. #define    ARG_VERBOSE    3
  52.  
  53.  
  54. /* String for c:Version */
  55. const char Version[] = "\0$VER: WBLaunch 1.1 (14.2.99)";
  56.  
  57. /* WBStart library name */
  58. const char WBStartName[] = "wbstart.library";
  59.  
  60. /* Text for extended help */
  61. const char Verbose[] =
  62.   "Copyright © 1998, 1999 Stephen Williams <sw@fysh.org>\n"
  63.   "wbstart.library is copyright © Stefan Becker\n"
  64.   "See WBLaunch.readme for terms of distribution";
  65.  
  66.  
  67. /*
  68.  * Functions
  69.  */
  70.  
  71.  
  72. /*
  73.  * NAME:
  74.  *    findFile - find directory in path containing a given file
  75.  *
  76.  * SYNOPSIS:
  77.  *    fileLock = findFile(filename)
  78.  *    BPTR findFile(char *)
  79.  *
  80.  * FUNCTION:
  81.  *    This routine searches the path for the given filename.  The
  82.  *    current directory is searched first.  If the file is not
  83.  *    found there, the path is searched.
  84.  *
  85.  * INPUTS:
  86.  *    filename - pointer to a null-terminated string
  87.  *
  88.  * RESULTS:
  89.  *    fileLock - BCPL pointer to a lock on the directory containing
  90.  *    the file, or 0 for failure
  91.  *
  92.  * NOTE:
  93.  *    It is your responsibility to unlock fileLock when you have
  94.  *    finished with it.
  95.  *
  96.  */
  97.  
  98. BPTR findFile(char * fileName)
  99. {
  100.   BPTR        fileLock;
  101.   BPTR *    pathPtr;
  102.   BPTR        prevDir;
  103.  
  104.   /* Try current directory */
  105.   if(fileLock = Lock(fileName, SHARED_LOCK)) {
  106.     #if DEBUG
  107.     Printf("Found \"%s\" in current directory\n", fileName);
  108.     #endif
  109.     UnLock(fileLock);
  110.     return DupLock(((struct Process *)FindTask(NULL))->pr_CurrentDir);
  111.   }
  112.  
  113.   /*
  114.    * Not there?  Look in the path.  This path traversal code is
  115.    * Deep Magic.  Don't blame me if you don't understand it.
  116.    * Neither do I any more ;-)  Future versions of this program
  117.    * will use dospath.library instead
  118.    */
  119.   for(pathPtr = (BPTR *)(((struct CommandLineInterface *)(((struct Process *)FindTask(NULL))->pr_CLI << 2))->cli_CommandDir << 2);
  120.                     pathPtr != NULL; pathPtr = (BPTR *)(pathPtr[0] << 2)) {
  121.     prevDir = CurrentDir(pathPtr[1]);
  122.     fileLock = Lock(fileName, SHARED_LOCK);
  123.     (void)CurrentDir(prevDir);
  124.     if(fileLock) {
  125.       #if DEBUG
  126.       Printf("Found \"%s\" in path\n", fileName);
  127.       #endif
  128.       UnLock(fileLock);
  129.       return DupLock(pathPtr[1]);
  130.     }
  131.   }
  132.  
  133.   return 0L;
  134. }
  135.  
  136.  
  137. /*
  138.  * Entry point
  139.  *
  140.  * Called from custom startup code.
  141.  *
  142.  * INPUTS:
  143.  *    None.
  144.  *
  145.  * RESULT:
  146.  *    AmigaDOS error code (0=OK, 5=WARN, 10=ERROR or 20=FAIL).
  147.  *
  148.  */
  149.  
  150. int shellmain(void)
  151. {
  152.   struct RDArgs *    anchor;
  153.   int            argCount = 0;
  154.   char **        arguments;
  155.   char *        argv0 = (char *)((((struct CommandLineInterface *)(((struct Process *)FindTask(NULL))->pr_CLI << 2))->cli_CommandName << 2) + 1);
  156.   char *        name;
  157.   int            rc = 20;
  158.   LONG            rdargs[4] = {0L, 0L, 0L, 0L};
  159.  
  160.   /* ReadArgs parsing */
  161.   anchor = ReadArgs("PROGRAM/A,ARGS/M,PRI=PRIORITY/N/K,VERBOSE/S",
  162.             &rdargs[0], NULL);
  163.   if(anchor) {
  164.     BPTR    fileOpen;
  165.     BPTR    newDirectory = 0L;
  166.     BPTR    oldDirectory =
  167.       ((struct Process *)FindTask(NULL))->pr_CurrentDir;
  168.     int        pathLen;
  169.     char *    pathStr = 0L;
  170.     
  171.     /* Got appropriate arguments */
  172.     name = (char *)rdargs[ARG_PROGRAM];
  173.     
  174.     /* Count arguments passed as ARGS/M */
  175.     for(arguments = (char **)rdargs[ARG_ARGUMENTS];
  176.     (arguments != NULL) && (*arguments != NULL);
  177.     arguments++)
  178.       argCount++;
  179.     arguments = (char **)rdargs[ARG_ARGUMENTS];
  180.     
  181.     /* See if the filename has no directory part.  We'll need to change
  182.        directory if this is the case */
  183.     if(!(pathLen = (int)FilePart(name) - (int)name)) {
  184.       /* Find the file in the current directory or path */
  185.       newDirectory = findFile(name);
  186.     } else {
  187.       /* Got a path part; change dir to there */
  188.       if(pathStr = AllocVec(pathLen + 4, MEMF_CLEAR | MEMF_REVERSE)) {
  189.     strncat(pathStr, name, pathLen);
  190. #ifdef DEBUG
  191.     Printf("Locking directory \"%s\", ", pathStr);
  192. #endif
  193.     newDirectory = Lock(pathStr, SHARED_LOCK);
  194.     /*oldDirectory = CurrentDir(newDirectory);*/
  195. #ifdef DEBUG
  196.     Printf("lock = %lx\n", newDirectory);
  197. #endif
  198.       }
  199.     }
  200.     
  201.     /* Make sure file exists */
  202.     (void)CurrentDir(newDirectory);
  203.     if(fileOpen = Open(FilePart(name), MODE_OLDFILE)) {
  204.       ULONG    firstLong = 0;
  205.       
  206.       /* Read first longword */
  207.       (void)Read(fileOpen, &firstLong, 4);
  208.       Close(fileOpen);
  209.       (void)CurrentDir(oldDirectory);
  210.       
  211.       /*
  212.        * Make sure we got an executable file header.
  213.        * NB: This will FAIL for binaries not in hunk format (e.g. ELF);
  214.        * this needs fixing in some way!
  215.        *
  216.        * I could just not bother with the check, but then wbstart.library
  217.        * might choke if someone passes a text file or something in.
  218.        *
  219.        * Maybe I should check for ELF headers as well?
  220.        * Or maybe ELF users should all change to WarpUp ;-)
  221.        */
  222.       if(firstLong == 0x000003f3) {
  223.     struct Library * privWBStartBase;
  224.     
  225.     /* Open library */
  226.     if(privWBStartBase = OpenLibrary((char *)WBStartName,
  227.                      (ULONG)WBSTART_VERSION)) {
  228.       int        goodArgs = 0;
  229.       int        count;
  230.       struct WBArg *wbArgs = NULL;
  231.       
  232.       /* Do Workbench argument parse */
  233.       if(argCount > 0) {
  234.         if(wbArgs = AllocVec(argCount * sizeof(struct WBArg),
  235.                  MEMF_ANY | MEMF_REVERSE)) {
  236.           char *        argDir;
  237.           char *        fname;
  238.           struct WBArg *    nextArg = wbArgs;
  239.           /* Process arguments one at a time */
  240. #ifdef DEBUG
  241.           Printf("Received %ld arguments\n", (ULONG)argCount);
  242. #endif
  243.           for(count = 0; count < argCount; count++) {
  244.         /* Go back to starting directory */
  245.         BPTR tempFile = Lock(arguments[count], SHARED_LOCK);
  246. #ifdef DEBUG
  247.         Printf("Processing arg #%ld, \"%s\":\n",
  248.                (ULONG)(count + 1),
  249.                arguments[count]);
  250. #endif
  251.         /* Try to open the file */
  252.         if(tempFile) {
  253.           UnLock(tempFile);
  254.           /* Allocate temp space */
  255.           if(argDir =
  256.              AllocVec(strlen(arguments[count]),
  257.                   MEMF_REVERSE | MEMF_CLEAR)) {
  258.             fname = FilePart(arguments[count]);
  259.             /* See if there's a directory component */
  260.             if(fname == arguments[count]) {
  261.               /* No, it's relative to start directory */
  262.               /* Need to DupLock() so we can safely UnLock() */
  263.               nextArg->wa_Lock = DupLock(oldDirectory);
  264.               nextArg->wa_Name = arguments[count];
  265.               nextArg++;
  266.               goodArgs++;
  267. #ifdef DEBUG
  268.               Printf("  Located relative to current directory\n");
  269. #endif
  270.             } else {
  271.               BPTR argLock;
  272.               strncat(argDir, arguments[count],
  273.                   (int)(fname - arguments[count]));
  274.               argLock = Lock(argDir, SHARED_LOCK);
  275.               /* Attempt lock on directory */
  276.               if(argLock) {
  277.             /* Got it; use that lock and the
  278.                filename component */
  279.             nextArg->wa_Lock = argLock;
  280.             nextArg->wa_Name = fname;
  281.             nextArg++;
  282.             goodArgs++;
  283. #ifdef DEBUG
  284.             Printf("  Located in directory \"%s\"\n", argDir);
  285. #endif
  286.               } else {
  287. #ifdef DEBUG
  288.             Printf("  Couldn't lock this argument\n");
  289. #endif
  290.               }
  291.             }
  292.             FreeVec(argDir);
  293.           }
  294.         } else {
  295.           Printf("%s warning: couldn't locate argument \"%s\"\n",
  296.              argv0, arguments[count]);
  297. #ifdef DEBUG
  298.           Printf("  Couldn't locate this argument\n");
  299. #endif
  300.         }
  301.           }
  302.         } else Printf("%s warning: couldn't allocate memory for arguments\n", argv0);
  303.       }
  304.       
  305.       /* Start the process */
  306.       if(newDirectory) {
  307.         char * argString;
  308. #ifdef DEBUG
  309.         Printf("Starting process with %ld arguments\n", goodArgs);
  310. #endif
  311.         
  312.         /* Verbose? */
  313.         if(rdargs[ARG_VERBOSE] &&
  314.            (argString = AllocVec(512L, MEMF_ANY | MEMF_REVERSE))) {
  315.           Printf("\n\033[1m%s\033[0m\n%s\n\n",
  316.              &Version[7], &Verbose[0]);
  317.           NameFromLock(newDirectory, argString, 511L);
  318.           AddPart(argString, FilePart(name), 511L);
  319.           Printf("Launching \"%s\" with %ld arguments%s", argString,
  320.              goodArgs, goodArgs ? ":\n" : "\n");
  321.           for(count = 0; count < goodArgs; count++) {
  322.         NameFromLock(wbArgs[count].wa_Lock, argString, 511);
  323.         Printf("  Argument #%ld: \"%s\", directory \"%s\"\n",
  324.                (ULONG)(count + 1),
  325.                wbArgs[count].wa_Name,
  326.                argString);
  327.         
  328.           }
  329.           Printf("\n");
  330.           FreeVec(argString);
  331.         }
  332.         
  333.         WBStartBase = privWBStartBase;
  334.         rc = !WBStartTags(
  335.                   WBStart_Priority,    rdargs[ARG_PRI] ? *(ULONG *)rdargs[ARG_PRI] : 0,
  336.                   WBStart_ArgumentCount,    goodArgs,
  337.                   WBStart_ArgumentList,    goodArgs ? wbArgs : NULL,
  338.                   WBStart_Name,        FilePart(name),
  339.                   WBStart_DirectoryLock,    newDirectory,
  340.                   0
  341.                   ) ? 0 : 10;
  342. #ifdef DEBUG
  343.         Printf("Process started\n");
  344. #endif
  345.       } else Printf("%s: initialization failed\n", argv0);
  346.       
  347.       /* Close things */
  348.       if(wbArgs) {
  349.         register int count;
  350.         /* Unlock all the directories we locked */
  351.         for(count = 0; count < goodArgs; count++)
  352.           UnLock(wbArgs[count].wa_Lock);
  353.         FreeVec(wbArgs);
  354.       }
  355.       CloseLibrary(privWBStartBase);
  356.       
  357.     } else Printf("%s: couldn't open %s v%ld+\n", argv0, WBStartName,
  358.               (ULONG)WBSTART_VERSION);
  359.     
  360.       } else PrintFault(ERROR_OBJECT_WRONG_TYPE, argv0);
  361.       
  362.     } else {
  363.       Printf("%s: couldn't open \"%s\"\n", argv0, name);
  364.       (void)CurrentDir(oldDirectory); /* changed prior to Open() */
  365.     }
  366.     
  367.     if(pathStr) FreeVec(pathStr);
  368.     /* Change directory back to where we started */
  369.     if(newDirectory) {
  370.       /*(void)CurrentDir(oldDirectory);*/
  371.       UnLock(newDirectory);
  372.     }
  373.     /* Free argument list */
  374.     FreeArgs(anchor);
  375.     
  376.   } else PrintFault(IoErr(), argv0); /* ReadArgs() failed */
  377.  
  378.   return rc;
  379. }
  380.